package kr.co.insoft.driver;

import java.io.Serializable;
import java.util.Collection;

import kr.co.insoft.driver.exception.DriverException;
import kr.co.insoft.driver.exception.NotSupportedException;
import kr.co.insoft.driver.model.HardwareProfileModel;
import kr.co.insoft.driver.model.ImageModel;
import kr.co.insoft.driver.model.InstanceModel;
import kr.co.insoft.driver.model.InstanceResultModel;
import kr.co.insoft.driver.model.KeyPairModel;
import kr.co.insoft.driver.model.OSTypeModel;
import kr.co.insoft.driver.model.RegionModel;
import kr.co.insoft.driver.model.SecurityModel;
import kr.co.insoft.driver.model.VolumeModel;
import kr.co.insoft.driver.model.ZoneModel;

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;

/**
 * Cloud Driver Interface
 * 
 * <pre>
 * 개발자에게 보여지는 Interface
 * 
 * 기본적으로 앞으로 구현해야하는 모든 Driver들은 아래 내용을 기본으로 구현해야함.
 * </pre>
 * 
 * @author Administrator
 * 
 */
public interface Drivers extends Serializable {

	public void setEndpoint(String endpoint);

	public void setAccessKey(String accessKey);

	public void setApiKey(String apiKey);

	public void setSecretKey(String secretKey);

	public void setUsername(String username);

	public void setProvider(String provider);

	/**
	 * 설정된 정보로 Connection 객체를 생성하여 반환한다.
	 * 
	 * @param endpoint를
	 *            입력할 경우에는 반드시 1개만 입력 없을 경우 입력하지 않아도 됨.
	 * @return
	 * @throws DriverException
	 */
	public Object getConnection(String endpoint) throws DriverException,
			NotSupportedException;

	/**
	 * 설정된 정보로 Connection 객체를 생성하여 반환한다.
	 * 
	 * @param endpoint
	 *            설정이 없는 경우 us-east-1 기본 설정 됨.
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Object getConnection() throws DriverException, NotSupportedException;

	/**
	 * 설정된 정보로 Region 목록을 반환한다.
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	@Cacheable("regions")
	public Collection<? extends RegionModel> getRegions()
			throws DriverException, NotSupportedException;

	/**
	 * 기본적으로 설정이 가능한 zone 목록을 반환한다.
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	@Cacheable("zones")
	public Collection<? extends ZoneModel> getZones() throws DriverException,
			NotSupportedException;

	/**
	 * 사용가능한 모든 Snapshot / Image 목록을 반환한다.
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends ImageModel> getImages() throws DriverException,
			NotSupportedException;

	/**
	 * 자신이 보유한 Snapshot / Image 목록을 반환한다.
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends ImageModel> getMyImages()
			throws DriverException, NotSupportedException;
	
	/**
	 * 자신이 보유한 Snapshot / Image 목록을 반환한다.
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends ImageModel> getMyImages(String zone)
			throws DriverException, NotSupportedException;

	/**
	 * Secure 목록
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends SecurityModel> getSecures()
			throws DriverException, NotSupportedException;

	/**
	 * Key 목록
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends KeyPairModel> getKeyPairs()
			throws DriverException, NotSupportedException;

	/**
	 * 인스턴스를 생성한다.
	 * 
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public InstanceResultModel createInstance(InstanceModel instance)
			throws DriverException, NotSupportedException;

	/**
	 * 인스턴스를 생성한다.
	 * 
	 * @param instance
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public InstanceResultModel createInstanceWithImage(InstanceModel instance)
			throws DriverException, NotSupportedException;

	/**
	 * 인스턴스 명칭을 변경한다.
	 * 
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public void renameInstance(InstanceModel instance) throws DriverException,
			NotSupportedException;

	/**
	 * 인스턴스 정보를 반환한다.
	 * 
	 * @param instanceIds
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends InstanceModel> getInstances(
			String... instanceIds) throws DriverException,
			NotSupportedException;

	/**
	 * 인스턴스 정보를 반환한다.
	 * 
	 * @param instanceIds
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends InstanceModel> getInstances(
			Collection<String> instanceIds) throws DriverException,
			NotSupportedException;

	/**
	 * region에 속하는 모든 인스턴스의 정보를 반환한다.
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends InstanceModel> getInstances()
			throws DriverException, NotSupportedException;

	/**
	 * 인스턴스를 시작한다.
	 * 
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends InstanceModel> startInstances(
			String... instanceIds) throws DriverException,
			NotSupportedException;

	/**
	 * 인스턴스를 시작한다.
	 * 
	 * @param instanceIds
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends InstanceModel> startInstances(
			Collection<String> instanceIds) throws DriverException,
			NotSupportedException;

	/**
	 * 인스턴스를 중지한다.
	 * 
	 * @param instanceIds
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends InstanceModel> stopInstances(
			String... instanceIds) throws DriverException,
			NotSupportedException;

	/**
	 * 인스턴스를 중지한다.
	 * 
	 * @param instanceIds
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends InstanceModel> stopInstances(
			Collection<String> instanceIds) throws DriverException,
			NotSupportedException;

	/**
	 * 인스턴스를 삭제한다.
	 * 
	 * @param instances
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends InstanceModel> terminateInstances(
			InstanceModel instances) throws DriverException,
			NotSupportedException;

	/**
	 * 인스턴스를 삭제한다.
	 * 
	 * @param instances
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends InstanceModel> terminateInstances(
			Collection<InstanceModel> instances) throws DriverException,
			NotSupportedException;

	/**
	 * DiskVolume 목록을 반환한다.
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends VolumeModel> getVolumes()
			throws DriverException, NotSupportedException;

	/**
	 * DiskVolume 목록을 반환한다.
	 * 
	 * @param volumeIds
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends VolumeModel> getVolumes(
			Collection<String> volumeIds) throws DriverException,
			NotSupportedException;

	/**
	 * Volume을 생성한다.
	 * 
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public void createVolumes() throws DriverException, NotSupportedException;

	/**
	 * Volume 을 attach 한다.
	 * 
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public void attachVolume() throws DriverException, NotSupportedException;

	/**
	 * OS type 정보를 반환한다.
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	public Collection<? extends OSTypeModel> getOsTypes()
			throws DriverException, NotSupportedException;

	/**
	 * Hardware 정보를 반환한다. (인스턴스 타입)
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	@Cacheable("hardwares")
	public Collection<? extends HardwareProfileModel> getHardwareProfiles()
			throws DriverException, NotSupportedException;
	
	/**
	 * Hardware 정보를 반환한다. (인스턴스 타입)
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	@Cacheable(value="hardwareByZones", key="#zone")
	public Collection<? extends HardwareProfileModel> getHardwareProfiles(String zone)
			throws DriverException, NotSupportedException;

	/**
	 * <pre>
	 * <i>asynchronous</i> method
	 * Instance 들의 상태를 반환한다.
	 * </pre>
	 * 
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	@Async
	public Collection<? extends InstanceModel> getCurrentState()
			throws DriverException, NotSupportedException;

	/**
	 * <pre>
	 * <i>asynchronous</i> method
	 * Instance 들의 상태를 반환한다.
	 * </pre>
	 * 
	 * @param instances
	 * @return
	 * @throws DriverException
	 * @throws NotSupportedException
	 */
	@Async
	public Collection<? extends InstanceModel> getCurrentState(
			Collection<? extends InstanceModel> instances)
			throws DriverException, NotSupportedException;
}
